package com.hyopt.common.push.util;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.hyopt.common.exception.MyException;
import com.hyopt.common.push.Notification.UmAndriodNotification;
import com.hyopt.common.push.Notification.UmIOSNotification;
import com.hyopt.common.push.Notification.UmNotification;
import com.hyopt.common.push.config.UmAndoridConfig;
import com.hyopt.common.push.config.UmConfig;
import com.hyopt.common.push.config.UmIosConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

@Slf4j
public class UmPushUtil {

    public static HttpClient newClient(){
        return HttpClientBuilder.create().build();
    }

    public static Map<String, Object> mapRemoveWithNull(Map<String, Object> map){
        Set<Map.Entry<String, Object>> set = map.entrySet();
        Iterator<Map.Entry<String, Object>> it = set.iterator();
        while(it.hasNext()){
            Map.Entry<String, Object> en = it.next();

            if(!(en.getValue() instanceof Map)){
                if(null == en.getValue() || "".equals(en.getValue())|| "null".equals(en.getValue())){
                    it.remove();
                }
            }else{
                Map map2 = (Map) en.getValue();
                mapRemoveWithNull(map2);
            }
        }
        return map;
    }

    /**
     * 必填字段校验
     * @param body
     */
    public static void checkBaseParam(Map body){
        if(ObjectUtil.isEmpty(body.get("appkey"))){
            throw new MyException("请求参数没有appkey或为空值",1000);
        }
        if(ObjectUtil.isEmpty(body.get("type"))){
            throw new MyException("请求参数没有type或为空值",1016);
        }
        String type=body.get("type")+"";
        if(UmConfig.CasetType.listcast.name().equals(type)||UmConfig.CasetType.unicast.name().equals(type)){
            if(ObjectUtil.isEmpty(body.get("device_tokens"))){
                throw new MyException("type为unicast或listcast时, 请求参数没有device_tokens或为空值",1015);
            }
        }
        if(UmConfig.CasetType.customizedcast.name().equals(type)){
            if(ObjectUtil.isEmpty(body.get("alias"))||ObjectUtil.isEmpty(body.get("file_id"))){
                throw new MyException("type为customizedcast时, 请求参数没有alias、file_id或皆为空值",2009);
            }
        }
        if(UmConfig.CasetType.groupcast.name().equals(type)){
            if(ObjectUtil.isEmpty(body.get("filter"))){
                throw new MyException("type为groupcast时, 请求参数没有filter",2009);
            }
        }
    }

    public static void checkPayload(String sys,Map params){
        if(!params.containsKey("payload")){
            throw new MyException("请求参数没有payload",1001);
        }
        Map payLoad=(Map)params.get("payload");
        if(!payLoad.containsKey("body")){
            throw new MyException("请求参数payload中, 没有body",1002);
        }
        Map payLoadBody=(Map)payLoad.get("body");//消息体
        if(UmConfig.Sys.Android.name().equals(sys)){
            if(ObjectUtil.isEmpty(payLoad.get("display_type"))){
                throw new MyException("请求参数payload中, 没有display_type或为空值",1004);
            }
            String display_type=payLoad.get("display_type").toString();
            if(UmConfig.DisplayType.notification.name().equals(display_type)){
                if(ObjectUtil.isEmpty(payLoadBody.get("ticker"))){
                    throw new MyException("payload.display_type为notification时, 请求参数payload.body中, 没有ticker参数",1008);
                }
                if(ObjectUtil.isEmpty(payLoadBody.get("title"))){
                    throw new MyException("payload.display_type为notification时, 请求参数payload.body中, 没有title参数",1009);
                }
                if(ObjectUtil.isEmpty(payLoadBody.get("text"))){
                    throw new MyException("payload.display_type为notification时, 请求参数payload.body中, 没有text参数",1010);
                }
            }
        }else if(UmConfig.Sys.IOS.name().equals(sys)){
            if(ObjectUtil.isEmpty(payLoad.get("aps"))){
                throw new MyException("请求参数payload中, 没有aps",400);
            }
        }
    }

    public static Map getPayload(Map content){
        Map payloadMap= (Map)content.get("payload");;
        if (ObjectUtil.isEmpty(payloadMap)) {
            payloadMap = new HashMap<>();
            content.put("payload", payloadMap);
        }
        return payloadMap;
    }

    public static void setPayLoad(Map content,String key, Object value){
        Map payloadMap=getPayload(content);
        payloadMap.put(key, value);
    }

    public static void setPolicy(Map content,String key, Object value){
        Map policyMap =(Map) content.get("policy");
        if(ObjectUtil.isEmpty(policyMap)){
            policyMap = new HashMap();
            content.put("policy", policyMap);
        }
        policyMap.put(key, value);
    }

    /**
     * 发送请求
     * @return
     */
    public static JSONObject sendUmRequest(UmNotification um){
        System.out.println(um.getSys()+"====参数：==="+um.getBody().toString());
        //UmPushUtil.checkBaseParam(um.getBody());
        StringBuffer result = new StringBuffer();
        JSONObject jsonObject = null;
        try {
            //获取参数
            if(um.getBody()!=null){
                //获取签名
                String signature="POST" + UmConfig.sendApiPath  + JSONObject.toJSONString(um.getBody()) + um.getAppMasterSecret();
                String url =  UmConfig.sendApiPath + "?sign=" + DigestUtils.md5Hex(signature.getBytes("utf8"));

                HttpPost post = new HttpPost(url);
                post.setHeader("User-Agent", "Mozilla/5.0");
                StringEntity se = new StringEntity(JSONObject.toJSONString(um.getBody()), "UTF-8");
                post.setEntity(se);
                log.info("Send the post request"+url);
                HttpResponse response = newClient().execute(post);
                //int status = response.getStatusLine().getStatusCode();
                BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                String line = "";
                while ((line = rd.readLine()) != null) {
                    result.append(line);
                }
                jsonObject = JSONObject.parseObject(result.toString());
                log.info(um.getSys()+"-友盟发送推送请求，返回结果 : " + result);
            }
        }catch (Exception ex){
            log.info(ex.getMessage());
        }
        return jsonObject;
    }


    /*IOS*/
    public static void setIOSBody(Map content){
        try{
            Iterator<Map.Entry<String, String>> entries = content.entrySet().iterator();
            while(entries.hasNext()) {
                Map.Entry<String, String> entry = entries.next();
                String key = entry.getKey();
                String value = entry.getValue();
                setIOSKeyValue(content,key,value);
            }
        }catch (Exception ex){
            log.info(ex.getMessage());
        }
    }

    public static void setIOSKeyValue(Map content,String key,Object value){
        if (UmConfig.ROOT_KEYS.contains(key)) {
            content.put(key, value);
        } else if (UmIosConfig.APS_KEYS.contains(key)) {
            setIOSAps(content, key, value);
        } else if (UmIosConfig.POLICY_KEYS.contains(key)) {
            UmPushUtil.setPolicy(content, key, value);
        } else {
            setIOSAps(content, key, value);
        }
    }

    public static void setIOSAps(Map content, String key, Object value){

        Map payloadMap=getPayload(content);
        Map apsMap =(Map) payloadMap.get("aps");
        if (ObjectUtil.isEmpty(apsMap)) {
            apsMap = new HashMap();
            payloadMap.put("aps", apsMap);
        }
        apsMap.put(key, value);
    }


    /* 安卓*/
    public static void setAndriodBody(Map content){
        try{
            Iterator<Map.Entry<String, String>> entries = content.entrySet().iterator();
            while(entries.hasNext()){
                Map.Entry<String, String> entry = entries.next();
                setAndriodKeyValue(content,entry.getKey(),entry.getValue());
            }
        }catch (Exception ex){
            log.info(ex.getMessage());
        }
    }

    public static void setAndriodKeyValue(Map content,String key,Object value){

        if (UmConfig.ROOT_KEYS.contains(key)) {
            // This key should be in the root level
            content.put(key, value);
        }else if (UmAndoridConfig.PAYLOAD_KEYS.contains(key)) {
            // This key should be in the body level
            setPayLoad(content,key,value);
        } else if (UmAndoridConfig.BODY_KEYS.contains(key)) {
            // This key should be in the body level
            setBody(content,key,value);
        } else if (UmAndoridConfig.POLICY_KEYS.contains(key)) {
            // This key should be in the body level
            UmPushUtil.setPolicy(content,key,value);
        } else {
            //Unknown key
            if(key.equals("extra")){
                setExtraField(content,value);
            }else if(key.equals("custom")){
                setCustom(content,value);
            }
        }
    }

    public static void setBody(Map content,String key, Object value){
        Map payloadMap=getPayload(content);
        Map bodyMap=(Map) payloadMap.get("body");
        if(ObjectUtil.isEmpty(bodyMap)){
            bodyMap = new HashMap<>();
            payloadMap.put("body", bodyMap);
        }
        bodyMap.put(key, value);
    }

    public static void setExtraField(Map content, Object value){
        Map extraFiledMap = (Map) content.get("payload");
        if (ObjectUtil.isEmpty(extraFiledMap)) {
            extraFiledMap = new HashMap();
            content.put("payload", extraFiledMap);
        }
        extraFiledMap.put("extra", value);
    }

    public static void setCustom(Map content,Object value){
        Map customMap = (Map) content.get("payload");
        if (ObjectUtil.isEmpty(customMap)) {
            customMap = new HashMap();
            content.put("payload", customMap);
        }
        Map bodyMap= (Map) content.get("body");
        if (ObjectUtil.isEmpty(bodyMap)) {
            bodyMap = new HashMap<>();
            content.put("body", bodyMap);
        }
        bodyMap.put("custom", value);
    }

    /**
     * 获取通知对象
     * @param sys-安卓/IOS
     * @param type-发送类型
     * @param map
     * @return
     */
    public static Object getUotificationBySys(String sys,String type,Map map){
        if(sys.equals(UmConfig.Sys.Android.name())){
            return new UmAndriodNotification(type,map);
        }else if(sys.equals(UmConfig.Sys.IOS.name())){
            return new UmIOSNotification(type,map);
        }
        return null;
    }

    public static Object getUotificationBySys(String sys,String type){
        if(sys.equals(UmConfig.Sys.Android.name())){
            return new UmAndriodNotification(type,null);
        }else if(sys.equals(UmConfig.Sys.IOS.name())){
            return new UmIOSNotification(type,null);
        }
        return null;
    }
}
